﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using SqlCeManager.Tools;
using DevExpress.XtraTab;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Grid;
using ProgNetComponentsDx.Language;
using System.Data.SqlServerCe;
using ProgNetComponentsDx.Options;

namespace SqlCeManager
{
    public partial class FormQuery : XtraForm
    {
        private ConnectionNode _Connection;
        private bool _NeedsCommit = false;
        public bool NeedsCommit
        {
            get { return _NeedsCommit; }
            set
            {
                _NeedsCommit = value;
                bbiCommit.Enabled = value;
                bbiRollBack.Enabled = value;
                if (!value)
                    NeedRefreshSchema = false;
            }
        }
        private bool NeedRefreshSchema
        {
            get;
            set;
        }
        private SqlCeConnection conn = null;
        private SqlCeTransaction tr = null;

        public FormQuery()
        {
            InitializeComponent();
            if (!this.IsDesignMode())
            {
                imageList1.Images.Add(SystemIcons.Error);
                imageList1.Images.Add(SystemIcons.Warning);
            }
        }
        
        public FormQuery(ConnectionNode node) : this()
        {
            _Connection = node;
            node.OwnedForms.Add(this);
            conn = new SqlCeConnection(node.ConnectionString);
            conn.Open();
        }
        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            base.OnFormClosed(e);
            if (tr != null)
            {
                tr.Rollback();
                tr.Dispose();
            }
            if (conn != null)
            {
                if (conn.State != ConnectionState.Closed)
                {
                    try { conn.Close(); }
                    catch { }
                    conn.Dispose();
                }
            }
        }
        private string Separator
        {
            get { return "^GO;?\\s*$"; }
        }

        private List<string> GetQueries()
        {
            List<string> l = new List<string>();
            if (meQuery.SelectionLength > 0)
            {
                l.Add(meQuery.SelectedText);
            }
            else
            {
                string str = meQuery.Text.ReplaceDoubleEOL();
                l.AddRange(str.XSplit(Separator, System.Text.RegularExpressions.RegexOptions.Multiline | System.Text.RegularExpressions.RegexOptions.IgnoreCase));
            }
            List<string> l2 = new List<string>();
            string s2 = "";
            foreach (string s in l)
            {
                s2 = s.Trim().TrimEnd(';');
                if (s2.IsNotNull())
                {
                    l2.Add(s2.ReplaceSingleEOL());
                }
            }
            return l2;
        }

        private void bbiExecute_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            List<string> list = GetQueries();
            XtraTabPage[] pages = xtraTabControl1.TabPages.ToArray();
            foreach (XtraTabPage p in pages)
            {
                xtraTabControl1.TabPages.Remove(p);
                p.Dispose();
            }
            pages = null;
            string ss = "";
            foreach (string s in list)
            {
                XtraTabPage page = null;
                SqlCeCommand cmd = null;
                ss = s.Trim();
                try
                {
                    if (ss.XMatch("CREATE\\s+") ||
                        ss.XMatch("ALTER\\s+"))
                    {
                        NeedRefreshSchema = true;
                    }
                    if (ss.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
                    {
                        DataTable dt = new DataTable();
                        _Connection.Adapter.SelectCommand.CommandText = ss;
                        _Connection.Adapter.Fill(dt);
                        page = CreateSelectPage(ss, dt);
                    }
                    else
                    {
                        cmd = conn.CreateCommand();
                        cmd.Transaction = GetTransaction();
                        cmd.CommandText = ss;
                        int i = cmd.ExecuteNonQuery();
                        page = CreateOtherPage(ss, i);
                    }
                }
                catch (Exception ex)
                {
                    page = CreateExceptionPage(ss, ex);
                    if (cmd != null)
                    {
                        try
                        {
                            cmd.Dispose();
                        }
                        catch { }
                    }
                }
                finally
                {
                    if (page != null)
                    {
                        xtraTabControl1.TabPages.Add(page);
                        if (page.Controls.Count > 0)
                        {
                            if (page.Controls[0] is GridControl)
                            {
                                ((page.Controls[0] as GridControl).MainView as GridView).BestFitWithName();
                            }
                        }
                        page.Text = "[     " + xtraTabControl1.TabPages.Count + "        ]";
                    }
                }
            }
        }

        private SqlCeTransaction GetTransaction()
        {
            if (tr == null)
                tr = conn.BeginTransaction();
            return tr;
        }
        private void bbiCommit_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (tr != null)
            {
                try
                {
                    tr.Commit();
                    if (NeedRefreshSchema)
                    {
                        this._Connection.GetTable("");
                    }
                }
                catch (Exception ex)
                {
                    this.ShowDxErrorDialog(ex.Message);
                }
                finally
                {
                    tr.Dispose();
                    tr = null;
                    NeedsCommit = false;
                }
            }
        }

        private void bbiRollBack_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (tr != null)
            {
                try
                {
                    tr.Rollback();
                }
                catch (Exception ex)
                {
                    this.ShowDxErrorDialog(ex.Message);
                }
                finally
                {
                    tr.Dispose();
                    tr = null;
                    NeedsCommit = false;
                }
            }
        }

        private XtraTabPage CreateStandardPage(string query)
        {
            XtraTabPage p = new XtraTabPage();
            MemoEdit m = new MemoEdit();
            m.Text = query.ReplaceSingleEOL();
            m.Dock = DockStyle.Top;
            m.Properties.ScrollBars = ScrollBars.Both;
            m.Properties.ReadOnly = true;
            m.Properties.WordWrap = false;
            int h = m.Text.Mesure(m.Font).Height + 40;
            if (h > 100)
                h = 100;

            m.Height = h;
            p.Controls.Add(m);
            return p;
        }
        private XtraTabPage CreateSelectPage(string query, DataTable dt)
        {
            XtraTabPage p = CreateStandardPage(query);
            GridControl gcMain = new GridControl();
            GridView gvMain = new GridView();
            ((System.ComponentModel.ISupportInitialize)(gvMain)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(gcMain)).BeginInit();
            gvMain.GridControl = gcMain;
            gvMain.Name = "gvMain"+xtraTabControl1.TabPages.Count;
            gvMain.OptionsView.ColumnAutoWidth = false;
            gvMain.OptionsBehavior.Editable = false;
            gcMain.Dock = System.Windows.Forms.DockStyle.Fill;
            gcMain.Location = new System.Drawing.Point(0, 0);
            gcMain.MainView = gvMain;
            gcMain.Name = "gcMain"+xtraTabControl1.TabPages.Count;
            gcMain.Size = new System.Drawing.Size(765, 534);
            gcMain.TabIndex = 4;
            gcMain.DataSource = dt;
            gcMain.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] {
            gvMain});
            ((System.ComponentModel.ISupportInitialize)(gvMain)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(gcMain)).EndInit();

            p.Controls.Add(gcMain);
            gcMain.BringToFront();
            return p;
        }
        private XtraTabPage CreateOtherPage(string query, int affectedRows)
        {
            bool partNeedCommit = affectedRows != 0;
            NeedsCommit |= partNeedCommit;
            

            XtraTabPage p = CreateStandardPage(query);
            if (!partNeedCommit)
                p.ImageIndex = 1;

            MemoEdit m = new MemoEdit();
            m.Text = ProgNetLanguage.sGetString("AFFFECTED_ROWS", affectedRows);
            m.Properties.ReadOnly = true;
            m.Dock = DockStyle.Fill;
            p.Controls.Add(m);
            m.BringToFront();
            return p;
        }
        private XtraTabPage CreateExceptionPage(string query, Exception ex)
        {
            XtraTabPage p = CreateStandardPage(query);
            p.ImageIndex = 0;
            MemoEdit m = new MemoEdit();
            m.Text = ProgNetLanguage.sGetString("QUERY_EXCEPTION");
            m.AppendText(ex.Message.ReplaceSingleEOL());
            m.Properties.ReadOnly = true;
            m.Dock = DockStyle.Fill;
            p.Controls.Add(m);
            m.BringToFront();
            return p;
        }

        private void btnAddToDbChanges_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            List<string> list = GetQueries();
            _Connection.SaveCommandsToDB(list);
        }

        public void ExecuteQuery(string query)
        {
            query = query.ReplaceDoubleEOL().ReplaceSingleEOL();
            meQuery.Text = query;
            bbiExecute.PerformClick();
        }
    }
}
